package com.xinhe.web.service;

import com.alibaba.fastjson.JSONObject;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.QueryResults;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.sun.org.apache.regexp.internal.RE;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.xinhe.web.common.BusinessException;
import com.xinhe.web.common.Result;
import com.xinhe.web.entity.*;
import com.xinhe.web.enums.*;
import com.xinhe.web.reposity.*;
import com.xinhe.web.response.AdoptedTreeOrderView;
import com.xinhe.web.selfpay.WeixinJsapiService;
import com.xinhe.web.session.UserSessionManager;
import com.xinhe.web.util.HttpServletRequestUtil;
import com.xinhe.web.util.Snowflake;
import com.xinhe.web.weixin.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.inject.Provider;
import javax.persistence.EntityManager;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.ValidationException;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
@Slf4j
@Service
public class AdoptedTreeOrderService {
    @Autowired
    MemberRepository memberRepository;
    @Autowired
    AdoptedTreeRepository adoptedTreeRepository;
    @Autowired
    AdoptedTreeOrderRepository adoptedTreeOrderRepository;
    @Autowired
    AdoptedRangeRepository adoptedRangeRepository;
    //查询工厂
    private JPAQueryFactory queryFactory;
    @Autowired
    private Provider<EntityManager> entityManager;
    @PostConstruct
    public void init() {
        queryFactory = new JPAQueryFactory(entityManager);
    }

    @Autowired
    TeaOilCardRecordService teaOilCardRecordService;
    @Autowired
    AssetCountService assetCountService;
    @Autowired
    AssetCountRepository assetCountRepository;
    @Autowired
    AssetDetailRepository assetDetailRepository;
    @Autowired
    ValueConfigRepository valueConfigRepository;
    @Autowired
    WeixinNotifyUtil weixinNotifyUtil;
    @Autowired
    WeixinTradeRepository weixinTradeRepository;
    @Autowired
    WeixinConfigRepository weixinConfigRepository;
    @Autowired
    WeixinTradeService weixinTradeService;
    @Autowired
    WeixinJsapiService weixinJsapiService;
    @Autowired
    WeixinTradeCpRepository weixinTradeCpRepository;

    /** 商户号 */
    public static String merchantId = "1616713201";
    /** 商户API私钥路径 */
    public static String privateKeyPath = "";
    /** 商户证书序列号 */
    public static String merchantSerialNumber = "57906AE4C493222D0DDD03D81A3A2F2AA93B8D19";
    /** 商户APIV3密钥 */
    public static String apiV3Key = "12345678901234567890ABCDEFGHIJKL";

    @Autowired
    private static ResourceLoader resourceLoader;

    /*spublic static NotificationConfig config = null;

    tatic {
        Resource resource = resourceLoader.getResource("classpath:cert/apiclient_key.pem");
        //String privateKeyPath = resource.getFile().getAbsolutePath();
        String privateKeyPath = null;
        try {
            privateKeyPath = resource.getFile().getPath();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 使用自动更新平台证书的RSA配置
        // 一个商户号只能初始化一个配置，否则会因为重复的下载任务报错
        config = new RSAAutoCertificateConfig.Builder()
                .merchantId(merchantId)
                .privateKeyFromPath(privateKeyPath)
                .merchantSerialNumber(merchantSerialNumber)
                .apiV3Key(apiV3Key)
                .build();
    }*/


    @Transactional
    public Result savePlatformAdoptedTreeOrder(Long adoptedTreeId, Integer amount, Long userId, String buyerRemark) {
        Member member = memberRepository.findByUserId(userId);
        if (null == member) {
            return Result.failed(20001,"用户不存在");
        }
        if (member.getAdoptionNum().intValue() < 10 && "创始人".equals(member.getRole()) && member.getIsImportMember().intValue() == 1 &&
                amount < 10) {
            throw new BusinessException(1004,"成为创始人首次购买数量不得小于10颗");
        }
        if (member.getAdoptionNum().intValue() + amount > 500) {
            throw new BusinessException(1003,String.format("认养油茶树的最高数量为500棵,您已购买%s颗", new Object[] { member.getAdoptionNum() }));
        }
        Optional<AdoptedTree> byId = adoptedTreeRepository.findById(adoptedTreeId);
        if (!byId.isPresent()) {
            return Result.failed(1005,"认养树不存在");
        }
        AdoptedTree adoptedTree = byId.get();
        AdoptedTreeOrder order = new AdoptedTreeOrder();
        order.setfUserId(member.getFUserId());
        order.setfAdoptedTreeId(adoptedTree.getId());
        order.setBuyerRemark(buyerRemark);
        order.setAmount(amount);
        order.setCode(generateOrderCode());
        //UN_PAY("未支付"),
        //PAY("已支付"),
        //CANCEL("已取消");
        order.setStatus("UN_PAY");
        order.setAdoptedYear(adoptedTree.getAdoptedYear());
        order.setTreeName(adoptedTree.getName());
        order.setTreeIconPath(adoptedTree.getIconPath());
        order.setPrice(adoptedTree.getPrice());
        AdoptedRange one = adoptedRangeRepository.findByOne();
        AdoptedRange two = adoptedRangeRepository.findByTwo();
        AdoptedRange three = adoptedRangeRepository.findByThree();
        if (one.getMinNum().intValue() <= amount && one.getMaxNum().intValue() >= amount) {
            order.setYunChaSeed(one.getYunChaSeed());
        } else if (two.getMinNum().intValue() <= amount && two.getMaxNum().intValue() >= amount) {
            order.setYunChaSeed(two.getYunChaSeed());
        } else {
            order.setYunChaSeed(three.getYunChaSeed());
        }
        order.setTeaOilCard(adoptedTree.getTeaOilCard());
        order.setConsumerGoldRedEnvelope(adoptedTree.getConsumerGoldRedEnvelope());
        order.setOrderYunChaSeed(order.getYunChaSeed().multiply(new BigDecimal(amount.intValue())));
        order.setOrderTeaOilCard(order.getTeaOilCard().multiply(new BigDecimal(order.getAmount().intValue())));
        order.setOrderConsumerGoldRedEnvelope(order.getConsumerGoldRedEnvelope().multiply(new BigDecimal(order.getAmount().intValue())));
        order.setTreeFee(order.getPrice().multiply(new BigDecimal(order.getAmount().intValue())));
        order.setOrderFee(order.getTreeFee().add(order.getOpexManagerFee()));
        order.setPayFee(order.getOrderFee());
        adoptedTreeOrderRepository.save(order);
        return Result.ok();
    }
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
    private String generateOrderCode() {
        StringBuilder code = new StringBuilder("LY");
        code.append(simpleDateFormat.format(new Date()));
        double codeRandom = Math.random() * 10000.0D;
        code.append((int)codeRandom);
        AdoptedTreeOrder order = adoptedTreeOrderRepository.findByCode(code.toString());
        if (order != null) {
            return generateOrderCode();
        }
        return code.toString();
    }
    @Transactional(rollbackFor = {Exception.class})
    public Result<Long> saveAdoptedTreeOrder(Long adoptedTreeId, Integer amount, Long userId, String buyerRemark) {
        Member member = memberRepository.findByUserId(userId);
        if (null == member) {
            return Result.failed(4001,"no_user");
        }
        if (member.getAdoptionNum().intValue() < 10 && "创始人".equals(member.getRole()) && member.getIsImportMember().intValue() == 1 &&
                amount < 10) {
            throw new BusinessException(1004,"成为创始人首次购买数量不得小于10颗");
        }
        if (member.getAdoptionNum().intValue() + amount > 500) {
            throw new BusinessException(1003,String.format("认养油茶树的最高数量为500棵,您已购买%s颗", new Object[] { member.getAdoptionNum() }));
        }
        Optional<AdoptedTree> byId = adoptedTreeRepository.findById(adoptedTreeId);
        if (!byId.isPresent()) {
            return Result.failed(1005,"认养树不存在");
        }
        AdoptedTree adoptedTree = byId.get();

        Integer count = adoptedTreeOrderRepository.findByCountUserIdAndStatus(member.getFUserId(),"UN_PAY");
        if (count.intValue() >= 1) {
            throw new BusinessException(1006,"您有一个未支付的订单，请勿重复下单");
        }
        AdoptedTreeOrder order = new AdoptedTreeOrder();
        order.setId(Snowflake.generateId());
        order.setfUserId(userId);
        order.setfAdoptedTreeId(adoptedTree.getId());
        order.setBuyerRemark(buyerRemark);
        order.setAmount(amount);
        order.setCode(generateOrderCode());
        order.setStatus("UN_PAY");
        order.setAdoptedYear(adoptedTree.getAdoptedYear());
        order.setTreeName(adoptedTree.getName());
        order.setTreeIconPath(adoptedTree.getIconPath());
        order.setPrice(adoptedTree.getPrice());
        AdoptedRange one = adoptedRangeRepository.findByOne();
        AdoptedRange two = adoptedRangeRepository.findByTwo();
        AdoptedRange three = adoptedRangeRepository.findByThree();
        if (one.getMinNum().intValue() <= amount.intValue() && one.getMaxNum().intValue() >= amount.intValue()) {
            order.setYunChaSeed(one.getYunChaSeed());
        } else if (two.getMinNum().intValue() <= amount.intValue() && two.getMaxNum().intValue() >= amount.intValue()) {
            order.setYunChaSeed(two.getYunChaSeed());
        } else {
            order.setYunChaSeed(three.getYunChaSeed());
        }
        order.setTeaOilCard(adoptedTree.getTeaOilCard());
        order.setConsumerGoldRedEnvelope(adoptedTree.getConsumerGoldRedEnvelope());
        order.setOrderYunChaSeed(order.getYunChaSeed().multiply(new BigDecimal(amount.intValue())));
        order.setOrderTeaOilCard(order.getTeaOilCard().multiply(new BigDecimal(order.getAmount().intValue())));
        order.setOrderConsumerGoldRedEnvelope(order.getConsumerGoldRedEnvelope().multiply(new BigDecimal(order.getAmount().intValue())));
        order.setTreeFee(order.getPrice().multiply(new BigDecimal(order.getAmount().intValue())));
        order.setOrderFee(order.getTreeFee().add(order.getOpexManagerFee()));
        order.setPayFee(order.getOrderFee());
        adoptedTreeOrderRepository.save(order);
        return Result.ok(order.getId());
    }
    public QueryResults<AdoptedTreeOrderView> pageAdoptedTreeOrder(Long userId,Long adoptedTreeId,String status,String code,String keyword,
                                                                   Date startTime,Date endTime, int pageNum, int pageSize) {
        QAdoptedTreeOrder qAdoptedTreeOrder = QAdoptedTreeOrder.adoptedTreeOrder;
        QMember qMember = QMember.member;
        OrderSpecifier<Date> sort = qAdoptedTreeOrder.createTime.desc();
        BooleanBuilder builder = new BooleanBuilder();
        if (!Objects.isNull(userId)){
            builder.and(qAdoptedTreeOrder.fUserId.eq(userId)).and(qAdoptedTreeOrder.status.eq("PAY"));
        }
        if (!Objects.isNull(adoptedTreeId)){
            builder.and(qAdoptedTreeOrder.fAdoptedTreeId.eq(adoptedTreeId));
        }
        if (StringUtils.isNotBlank(code)){
            builder.and(qAdoptedTreeOrder.code.eq(code));
        }
        if (!Objects.isNull(status)){
            builder.and(qAdoptedTreeOrder.status.eq(status));
        }
        if (!Objects.isNull(keyword)){
            builder.and(qAdoptedTreeOrder.code.contains(keyword).or(qMember.name.contains(keyword))
                    .or(qMember.mobile.contains(keyword)));
        }
        if (!Objects.isNull(startTime) && !Objects.isNull(endTime)){
            builder.and(qAdoptedTreeOrder.payTime.between(startTime,endTime));
        }
        QueryResults<AdoptedTreeOrderView> adoptedTreeOrderViewQueryResults = queryFactory.select(
                        Projections.bean(
                                AdoptedTreeOrderView.class,
                                qAdoptedTreeOrder.id,
                                qAdoptedTreeOrder.code,
                                qAdoptedTreeOrder.fUserId,
                                qAdoptedTreeOrder.fAdoptedTreeId,
                                qAdoptedTreeOrder.payTime,
                                qAdoptedTreeOrder.payChannel,
                                qAdoptedTreeOrder.treeName,
                                qAdoptedTreeOrder.treeIconPath,
                                qAdoptedTreeOrder.price,
                                qAdoptedTreeOrder.opexManagerFee,
                                qAdoptedTreeOrder.amount,
                                qAdoptedTreeOrder.yunChaSeed,
                                qAdoptedTreeOrder.teaOilCard,
                                qAdoptedTreeOrder.consumerGoldRedEnvelope,
                                qAdoptedTreeOrder.buyerRemark,
                                qAdoptedTreeOrder.startTime,
                                qAdoptedTreeOrder.endTime,
                                qAdoptedTreeOrder.status,
                                qAdoptedTreeOrder.payFee,
                                qAdoptedTreeOrder.orderFee,
                                qAdoptedTreeOrder.orderYunChaSeed,
                                qAdoptedTreeOrder.orderTeaOilCard,
                                qAdoptedTreeOrder.orderConsumerGoldRedEnvelope,
                                qAdoptedTreeOrder.treeFee,
                                qAdoptedTreeOrder.adoptedYear,
                                qAdoptedTreeOrder.additionalYunChaSeed,
                                qAdoptedTreeOrder.isGive,
                                qAdoptedTreeOrder.createTime,
                                qMember.mobile,
                                qMember.name,
                                qMember.parentCode,
                                qMember.code.as("memberCode")
                        )
                ).from(qAdoptedTreeOrder)
                .leftJoin(qMember).on(qAdoptedTreeOrder.fUserId.eq(qMember.fUserId))
                .where(builder).offset(pageNum * pageSize).limit(pageSize).orderBy(sort).fetchResults();
        //对分页结果进行处理
        List<AdoptedTreeOrderView> results = adoptedTreeOrderViewQueryResults.getResults();
        // 创建一个用于存储修改后元组对象的列表
        List<AdoptedTreeOrderView> modifiedResults = new ArrayList<>();
        for (AdoptedTreeOrderView adoptedTreeOrderView : results) {
            //所属创始人。根据推荐人一直往上找，直到找到推荐人是创始人的为止。根据订单编号查询tb_member表，查询出来推荐人的订单编号
            //调用mysql函数获取
            String rootName = memberRepository.queryFunder(adoptedTreeOrderView.getMemberCode());
            if (StringUtils.isNotBlank(rootName)){
                adoptedTreeOrderView.setRootName(rootName);
            }
            //推荐人。根据parentCode订单编号查询tb_member表，查询出来推荐人的名字
            String parentName = memberRepository.queryParentName(adoptedTreeOrderView.getParentCode());
            if (StringUtils.isNotBlank(parentName)){
                adoptedTreeOrderView.setParentName(parentName);
            }
            // 将修改后的元组对象添加到列表中
            modifiedResults.add(adoptedTreeOrderView);
        }
        // 创建一个新的QueryResults对象，包含修改后的分页记录
        QueryResults<AdoptedTreeOrderView> modifiedQueryResults = new QueryResults<>(
                modifiedResults,
                adoptedTreeOrderViewQueryResults.getTotal(),
                adoptedTreeOrderViewQueryResults.getOffset(),
                adoptedTreeOrderViewQueryResults.getLimit()
        );
        return modifiedQueryResults;

    }
    @Transactional
    public Result updateSeedYunChaSeed(Long orderId, BigDecimal additionalYunChaSeed) {
        AdoptedTreeOrder adoptedTreeOrder = this.adoptedTreeOrderRepository.findById(orderId).get();
        adoptedTreeOrder.setAdditionalYunChaSeed(additionalYunChaSeed);
        adoptedTreeOrder.setIsGive(Integer.valueOf(1));
        adoptedTreeOrderRepository.saveAndFlush(adoptedTreeOrder);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date parse = null;
        try {
            parse = format.parse("2024-01-01");
            if (parse.compareTo(new Date()) > 0) {
                //this.assetCountService.saveRemainderAsset(new AssetTradeModel(adoptedTreeOrder.getUserId(), (IAssetType)EAssetType.YUN_CHA_SEED, (IEnumConfig)EAssetTradeType.ADDITIONAL_GIFT_YUN_CHA_SEED, additionalYunChaSeed, null));
                //1、保存资产流水。资产类型是茶油卡。交易类型是兑换茶油。交易金额记作：负兑换数量
                //2、更新资产统计表AssetCount里面的剩余茶油卡数量remainder
                teaOilCardRecordService.saveRemainderAsset(adoptedTreeOrder.getfUserId(),"YUN_CHA_SEED","ADDITIONAL_GIFT_YUN_CHA_SEED",
                        additionalYunChaSeed,null);
            } else {
                //this.assetCountService.saveRemainderAsset(new AssetTradeModel(adoptedTreeOrder.getUserId(), (IAssetType)EAssetType.NEW_YUN_CHA_SEED, (IEnumConfig)EAssetTradeType.ADDITIONAL_GIFT_YUN_CHA_SEED, additionalYunChaSeed, null));
                teaOilCardRecordService.saveRemainderAsset(adoptedTreeOrder.getfUserId(),"NEW_YUN_CHA_SEED","ADDITIONAL_GIFT_YUN_CHA_SEED",
                        additionalYunChaSeed,null);
            }
        }catch (ParseException e) {
            e.printStackTrace();
        }
        return Result.ok();
    }
    @Transactional
    public Result updateCancelSeedYunChaSeed(Long orderId, BigDecimal additionalYunChaSeed) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        AdoptedTreeOrder adoptedTreeOrder = adoptedTreeOrderRepository.findById(orderId).get();
        if (adoptedTreeOrder.getAdditionalYunChaSeed().compareTo(additionalYunChaSeed) < 0) {
            throw new BusinessException(9001,"取消数量不能超过剩余数量");
        }
        adoptedTreeOrder.setAdditionalYunChaSeed(adoptedTreeOrder.getAdditionalYunChaSeed().subtract(additionalYunChaSeed));
        adoptedTreeOrder.setIsGive(Integer.valueOf(0));
        adoptedTreeOrderRepository.saveAndFlush(adoptedTreeOrder);
        try {
            AssetCount assetCount1;
            Date date = format.parse("2024-01-01");
            if (date.compareTo(new Date()) > 0) {
                assetCount1 = this.assetCountService.initAssetCount("YUN_CHA_SEED", adoptedTreeOrder.getfUserId());
            } else {
                assetCount1 = this.assetCountService.initAssetCount("NEW_YUN_CHA_SEED", adoptedTreeOrder.getfUserId());
            }
            BigDecimal remainder1 = assetCount1.getRemainder().add(additionalYunChaSeed.negate());
            assetCount1.setRemainder(remainder1);
            this.assetCountRepository.saveAndFlush(assetCount1);
            //AssetDetailCount assetDetailCount = new AssetDetailCount();
            AssetDetail assetDetailCount = new AssetDetail();
            assetDetailCount.setfUserId(adoptedTreeOrder.getfUserId());
            if (date.compareTo(new Date()) > 0) {
                assetDetailCount.setAssetType(EAssetType.YUN_CHA_SEED.getName());
            } else {
                assetDetailCount.setAssetType(EAssetType.NEW_YUN_CHA_SEED.getName());
            }
            assetDetailCount.setTradeType(EAssetTradeType.ADDITIONAL_GIFT_YUN_CHA_SEED.getName());
            assetDetailCount.setRemainder(remainder1);
            assetDetailCount.setTradeAmount(additionalYunChaSeed.negate());
            assetDetailCount.setCreateTime(adoptedTreeOrder.getStartTime());
            this.assetDetailRepository.save(assetDetailCount);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return Result.ok();
    }
    @Transactional
    public Result automaticCancelOvertimeOrder() {
        Integer teamTimeoutMinuteStr = 0;
        //获取配置的认养订单超时分钟,30
        Optional<ValueConfig> valueConfig = valueConfigRepository.findById("timeout_hour");
        if (valueConfig.isPresent() && StringUtils.isNotBlank(valueConfig.get().getValue())){
            teamTimeoutMinuteStr = Integer.valueOf(valueConfig.get().getValue());
        }
        List<AdoptedTreeOrder> orderList = this.adoptedTreeOrderRepository.findOvertimeOrder(teamTimeoutMinuteStr);
        if (CollectionUtils.isNotEmpty(orderList)) {
            for (AdoptedTreeOrder courtOrder : orderList) {
                courtOrder.setStatus("CANCEL");
                this.adoptedTreeOrderRepository.saveAndFlush(courtOrder);
            }
        }
        return Result.ok();
    }

    @Transactional(rollbackFor = {Exception.class})
    public Result responseJsapiPay() {
        Result result = this.getWeixinPayNotifyDataAndValidateAndUpdateWeixinTrade();
        if (0 != result.getCode()) {
            return result;
        }
        WeixinPayNotifyView view = (WeixinPayNotifyView)result.getData();
        WeixinTrade weixinTrade = view.getWeixinTrade();
        AdoptedTreeOrder order = this.adoptedTreeOrderRepository.findById(weixinTrade.getDataId()).get();
        if (order != null && order.getStatus().equals("UN_PAY")) {
            order.setPayChannel("WEIXIN_JSAPI");
            order.setPayTime(new Date());
            paySuccess(order);
        }
        return result;
    }

    @Transactional(rollbackFor = {Exception.class})
     public Result getWeixinPayNotifyDataAndValidateAndUpdateWeixinTrade() {
       Map<String, String> notifyData = this.weixinNotifyUtil.getNotifyData();
       Long tradeId = Long.valueOf(notifyData.get("attach"));
       WeixinTrade trade = this.weixinTradeRepository.findById(tradeId).get();
       WeixinConfig weixinConfig = this.weixinConfigRepository.findById(trade.getConfigId()).get();
       String weixinTradeId = notifyData.get("transaction_id");
       if (2 == trade.getTradeStatus().intValue()) {
         return Result.ok(null,"已回调成功");
       }
       Boolean valid = false;
       try {
         valid = Boolean.valueOf(WXPayUtil.isSignatureValid(notifyData, weixinConfig.getPayKey()));
       } catch (Exception e) {
         e.printStackTrace();
       }
       if (valid.booleanValue()) {
         trade.setTradeStatus(Integer.valueOf(2));
         trade.setWeixinTradeId(weixinTradeId);
         trade.setNotifyInfo(JSONObject.toJSONString(notifyData));
         this.weixinTradeRepository.saveAndFlush(trade);
         WeixinPayNotifyView view = new WeixinPayNotifyView();
         view.setNotifyData(notifyData);
         view.setWeixinTrade(trade);
           return Result.ok(view,"<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>");
       } else {
           return Result.failed(2200,"不合法的请求信息<xml><return_code><![CDATA[FAIL]]></return_code></xml>");
       }
     }

    @Transactional(rollbackFor = {Exception.class})
    public Result requestJsapiPayParam(Long orderId, String openId) {
        System.out.println("openId为:" + openId);
        Result<WeixinJsapiPayParamView> result = new Result();
        if (orderId == null) {
            return Result.failed(2201,"订单Id不能为空");
        }
        AdoptedTreeOrder order = this.adoptedTreeOrderRepository.findById(orderId).get();
        if (order == null){
            return Result.failed(2202,"订单不存在");
        }
        if (!order.getStatus().equals("UN_PAY")) {
            return Result.failed(2203,String.format("订单%s", new Object[]{order.getStatus()}));
        }
        //组装参数调用微信sdk
        PrepayRequest request = new PrepayRequest();
        request.setAppid("wx2425d0af98810b00");
        request.setMchid("1616713201");
        request.setDescription("认养支付");
        //商户订单号，同一个商户号下唯一。
        request.setOutTradeNo(order.getId().toString());
        request.setNotifyUrl("http://1941w5190a.yicp.fun:49760/test/acceptWeixin");
        Amount amount = new Amount();
        //转转换为分
        amount.setTotal(order.getPayFee().intValue()*100);
        request.setAmount(amount);
        //用户在普通商户AppID下的唯一标识。 下单前需获取到用户的OpenID，
        Payer payer = new Payer();
        payer.setOpenid(openId);
        //payer.setOpenid("olYZb5aMoVTziZtD8MYK5dIV8TmE88");
        //request.setAttach();
        request.setPayer(payer);
        Result res = this.weixinJsapiService.jsapiPay(request);
        return res;
        /*WeixinJsapiPayParamModel payModel = new WeixinJsapiPayParamModel();
        payModel.setDataId(order.getId());
        payModel.setDataType("认养云茶籽支付");
        payModel.setBody("认养云茶籽支付");
        payModel.setFee(order.getPayFee());
        payModel.setNotifyUrl("/adoptedTreeOrder/responseJsapiPay");
        payModel.setOpenId(openId);
        return this.weixinTradeService.requestWeixinPayParam((WeixinPayParamModel)payModel);*/
    }

    private void paySuccess(AdoptedTreeOrder order) {
        order.setStatus("PAY");
        Calendar calendar = Calendar.getInstance();
        //认养时间
        order.setStartTime(calendar.getTime());
        calendar.add(1, order.getAdoptedYear().intValue());
        //到期时间
        order.setEndTime(calendar.getTime());
        this.adoptedTreeOrderRepository.saveAndFlush(order);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        //订单总赠送的云茶籽
        if (order.getOrderYunChaSeed().compareTo(BigDecimal.ZERO) > 0) {
            Date parse = null;
            try {
                Result<AssetDetail> beanResult;
                parse = format.parse("2024-01-01");
                if (parse.compareTo(new Date()) > 0) {
                    beanResult = this.assetCountService.saveRemainderAsset(order.getfUserId(),"YUN_CHA_SEED","ADOPTED_TREE",order
                            .getOrderYunChaSeed(), order.getId(),"",new Date());
                } else {
                    beanResult = this.assetCountService.saveRemainderAsset(order.getfUserId(), "NEW_YUN_CHA_SEED","ADOPTED_TREE", order
                            .getOrderYunChaSeed(), order.getId(),"",new Date());
                }
                if (0 != beanResult.getCode()) {
                    log.error("认养云茶籽失败【{}】,订单：{}", EAssetType.YUN_CHA_SEED.getName(), order.getId());
                }
            }
            catch (Exception e) {
                e.printStackTrace();
            }
        }
        //订单总赠送的茶油卡
        if (order.getOrderTeaOilCard().compareTo(BigDecimal.ZERO) > 0) {
            Result<AssetDetail> beanResult = this.assetCountService.saveRemainderAsset(order.getfUserId(),"TEA_OIL_CARD","ADOPTED_OIL_CARD", order
                    .getOrderTeaOilCard(), order.getId(),"",new Date());
            if (0 != beanResult.getCode()) {
                log.error("认养云茶籽失败【{}】,订单：{}", EAssetType.TEA_OIL_CARD.getName(), order.getId());
            }
        }
        //订单总赠送的消费金红包
        if (order.getOrderConsumerGoldRedEnvelope().compareTo(BigDecimal.ZERO) > 0) {
            Result<AssetDetail> beanResult = this.assetCountService.saveRemainderAsset(order.getfUserId(),"CONSUMER_GOLD_RED_ENVELOPE","ADOPTED_CONSUMER_GOLD_RED_ENVELOPE", order
                    .getOrderConsumerGoldRedEnvelope(), order.getId(),"",new Date());
            if (0 != beanResult.getCode()) {
                log.error("认养云茶籽失败【{}】,订单：{}", EAssetType.CONSUMER_GOLD_RED_ENVELOPE.getName(), order.getId());
            }
        }
        //1、成功认养后，芯禾会员升级为家园天使 2、更新认养总的数量
        Member member = this.memberRepository.findByUserId(order.getfUserId());
        if ("COMMON".equals(member.getLevel())) {
            member.setLevel("HOME_ANGEL");
        }
        member.setAdoptionDate(new Date());
        member.setAdoptionNum(Integer.valueOf(member.getAdoptionNum().intValue() + order.getAmount().intValue()));
        this.memberRepository.saveAndFlush(member);
        //是否导入用户 0是 1否
        if (1 == member.getIsImportMember().intValue()) {
            //查询配置的创始人首次购买数量，20
            Optional<ValueConfig> optional = valueConfigRepository.findById("founder_first_purchase_quantity");
            Integer founder_first_purchase_quantity = Integer.valueOf(optional.get().getValue());
            if ("FOUNDER".equals(member.getRole()) && member.getAdoptionNum().intValue() >= founder_first_purchase_quantity &&
                    StringUtils.isNotBlank(member.getParentCode())) {
                Member parentMember = this.memberRepository.findByCode(member.getParentCode());
                if (null != parentMember) {
                    //更新推荐人脱离关系前的认养数量
                    parentMember.setDisengageNo(order.getAmount());//todo
                    this.memberRepository.saveAndFlush(parentMember);
                    Result result = this.assetCountService.findByTypeAndUserId("YUN_CHA_SEED", parentMember.getFUserId());
                    AssetCount assetCount = (AssetCount) result.getData();
                    //更新一下推荐人资产。查询一下配置的“推荐创始人奖励” 2250
                    Optional<ValueConfig> valueConfigOptional = valueConfigRepository.findById("recommended_founder_rewards");
                    BigDecimal recommended_founder_rewards = new BigDecimal(valueConfigOptional.get().getValue());
                    this.assetCountService.saveRemainderAsset(parentMember.getFUserId(),"RMB","FOUNDER_REWARDS",recommended_founder_rewards, parentMember.getId(),
                            String.format("推荐创始人%s%s认养%s棵获得奖励", new Object[] { member.getName(), member.getMobile().replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"), order.getAmount() }),new Date());
                    Result result1 = this.assetCountService.findByTypeAndUserId("YUN_CHA_SEED", parentMember.getFUserId());
                    AssetCount assetCount1 = (AssetCount) result1.getData();
                    //查询配置的推荐创始人解冻云茶籽，2250
                    Optional<ValueConfig> valueConfigOptiona2 = valueConfigRepository.findById("recommend_founder_thawing");
                    BigDecimal recommend_founder_thawing = new BigDecimal(valueConfigOptiona2.get().getValue());
                    //如果推荐人剩余的>配置的2250
                    if (assetCount1.getRemainder().compareTo(recommend_founder_thawing) >= 0) {
                        //更新一下推荐人资产。推荐创始人解冻云茶籽
                        Result beanResult1 = this.assetCountService.saveRemainderAsset(parentMember.getFUserId(),"YUN_CHA_SEED","RECOMMEND_FOUNDER_THAWING",
                                recommend_founder_thawing.negate(), order.getId(),"",new Date());
                        if (0 == beanResult1.getCode()) {
                            this.assetCountService.saveRemainderAsset(parentMember.getFUserId(),"RMB","RECOMMEND_FOUNDER_THAWING",
                                    recommend_founder_thawing, order.getId(),"",new Date());
                        }
                    }else{
                        //如果推荐人剩余的不够解冻配置的2250,那就剩多少解冻多少
                        BigDecimal difference = recommend_founder_thawing.subtract(assetCount.getRemainder());
                        if (assetCount.getRemainder().compareTo(BigDecimal.ZERO) > 0) {
                            BigDecimal remainder = assetCount.getRemainder();
                            Result beanResult1 = this.assetCountService.saveRemainderAsset(parentMember.getFUserId(),"YUN_CHA_SEED","RECOMMEND_FOUNDER_THAWING", remainder
                                    .negate(), order.getId(),"",new Date());
                            if (0 == beanResult1.getCode()) {
                                this.assetCountService.saveRemainderAsset(parentMember.getFUserId(),"RMB","RECOMMEND_FOUNDER_THAWING", remainder, order
                                        .getId(),"",new Date());
                            }
                        }
                        //查询新资产类型的（20240101之后认养的）剩余量
                        Result result2 = this.assetCountService.findByTypeAndUserId("NEW_YUN_CHA_SEED", parentMember.getFUserId());
                        AssetCount assetCount2 = (AssetCount) result2.getData();
                        if (null != assetCount2 && assetCount2.getRemainder().compareTo(BigDecimal.ZERO) > 0) {
                            //够的话继续解冻
                            if (assetCount2.getRemainder().compareTo(difference) > 0) {
                                Result beanResult2 = this.assetCountService.saveRemainderAsset(parentMember.getFUserId(),"NEW_YUN_CHA_SEED","RECOMMEND_FOUNDER_THAWING", difference
                                        .negate(), order.getId(),"",new Date());
                                if (0 == beanResult2.getCode()) {
                                    this.assetCountService.saveRemainderAsset(parentMember.getFUserId(),"RMB","RECOMMEND_FOUNDER_THAWING", difference, order
                                            .getId(),"",new Date());
                                }
                            } else {
                                //够的话解冻新资产类型剩余的
                                BigDecimal remainder = assetCount2.getRemainder();
                                Result beanResult2 = this.assetCountService.saveRemainderAsset(parentMember.getFUserId(),"NEW_YUN_CHA_SEED","RECOMMEND_FOUNDER_THAWING", remainder
                                        .negate(), order.getId(),"",new Date());
                                if (0 == beanResult2.getCode()) {
                                    this.assetCountService.saveRemainderAsset(parentMember.getFUserId(),"RMB","RECOMMEND_FOUNDER_THAWING", remainder, order
                                            .getId(),"",new Date());
                                }
                            }
                        }
                    }
                    //接触推荐关系
                    member.setParentCode(null);
                    this.memberRepository.saveAndFlush(member);
                }
            }
        }
        //有推荐人
        if (StringUtils.isNotBlank(member.getParentCode())) {
            Member parent = this.memberRepository.findByCode(member.getParentCode());
            if (parent != null) {
                //查询配置的直推解冻云茶籽数量，75
                Optional<ValueConfig> optional = valueConfigRepository.findById("two_thaw_yun_cha_seed_amount");
                BigDecimal twoYunChaSeed = new BigDecimal(optional.get().getValue());
                BigDecimal twoYunChaSeedMoney = twoYunChaSeed.multiply(new BigDecimal(order.getAmount().intValue()));
                Result result = this.assetCountService.findByTypeAndUserId("YUN_CHA_SEED", parent.getFUserId());
                AssetCount assetCount = (AssetCount) result.getData();
                //剩余量够的话直接解冻
                if (assetCount.getRemainder().compareTo(twoYunChaSeedMoney) >= 0) {
                    Result beanResult = this.assetCountService.saveRemainderAsset(parent.getFUserId(),"YUN_CHA_SEED","TWO_THAW_YUN_CHA_SEED", twoYunChaSeedMoney
                            .negate(), order.getId(),"",new Date());
                    if (0 == beanResult.getCode()) {
                        this.assetCountService.saveRemainderAsset(parent.getFUserId(),"RMB","TWO_THAW_YUN_CHA_SEED", twoYunChaSeedMoney, order
                                .getId(),"",new Date());
                    }
                } else {
                    //剩余量不够的话有多少解冻多少
                    BigDecimal difference = twoYunChaSeedMoney.subtract(assetCount.getRemainder());
                    if (assetCount.getRemainder().compareTo(BigDecimal.ZERO) > 0) {
                        BigDecimal remainder = assetCount.getRemainder();
                        Result beanResult = this.assetCountService.saveRemainderAsset(parent.getFUserId(),"YUN_CHA_SEED","TWO_THAW_YUN_CHA_SEED", remainder
                                .negate(), order.getId(),"",new Date());
                        if (0 == beanResult.getCode()) {
                            this.assetCountService.saveRemainderAsset(parent.getFUserId(),"RMB","TWO_THAW_YUN_CHA_SEED", remainder, order
                                    .getId(),"",new Date());
                        }
                    }
                    //查询新资产类型的（20240101之后认养的）剩余量,接着解冻
                    Result result3 = this.assetCountService.findByTypeAndUserId("NEW_YUN_CHA_SEED", parent.getFUserId());
                    AssetCount assetCount3 = (AssetCount) result3.getData();
                    if (null != assetCount3 &&
                            assetCount3.getRemainder().compareTo(BigDecimal.ZERO) > 0) {
                        if (assetCount3.getRemainder().compareTo(difference) > 0) {
                            Result beanResult2 = this.assetCountService.saveRemainderAsset(parent.getFUserId(),"NEW_YUN_CHA_SEED","TWO_THAW_YUN_CHA_SEED", difference
                                    .negate(), order.getId(),"",new Date());
                            if (0 == beanResult2.getCode()) {
                                this.assetCountService.saveRemainderAsset(parent.getFUserId(),"RMB","TWO_THAW_YUN_CHA_SEED", difference, order
                                        .getId(),"",new Date());
                            }
                        } else {
                            BigDecimal remainder = assetCount3.getRemainder();
                            Result beanResult2 = this.assetCountService.saveRemainderAsset(parent.getFUserId(),"NEW_YUN_CHA_SEED","TWO_THAW_YUN_CHA_SEED", remainder
                                    .negate(), order.getId(),"",new Date());
                            if (0 == beanResult2.getCode()) {
                                this.assetCountService.saveRemainderAsset(parent.getFUserId(),"RMB","TWO_THAW_YUN_CHA_SEED", remainder, order
                                        .getId(),"",new Date());
                            }
                        }
                    }
                }
                //配置的直推奖励余额,225
                Optional<ValueConfig> optiona2 = valueConfigRepository.findById("two_thaw_reward");
                BigDecimal twoFee = new BigDecimal(optiona2.get().getValue());
                BigDecimal twoFeeMoney = twoFee.multiply(new BigDecimal(order.getAmount().intValue()));
                this.assetCountService.saveRemainderAsset(parent.getFUserId(),"RMB","TWO_THAW_REWARD", twoFeeMoney, order
                        .getId(), String.format("直推%s%s认养%s棵获得奖励", new Object[] { member.getName(), member.getMobile().replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"), order.getAmount() }),new Date());
                //推荐人有上级推荐人
                if (StringUtils.isNotBlank(parent.getParentCode())) {
                    Member threeMember = this.memberRepository.findByCode(parent.getParentCode());
                    if (threeMember != null) {
                        //配置的间推解冻云茶籽数量,45
                        Optional<ValueConfig> optiona3 = valueConfigRepository.findById("three_thaw_yun_cha_seed_amount");
                        BigDecimal threeYunChaSeed = new BigDecimal(optiona3.get().getValue());
                        BigDecimal threeYunChaSeedMoney = threeYunChaSeed.multiply(new BigDecimal(order.getAmount().intValue()));
                        Result result1 = this.assetCountService.findByTypeAndUserId("YUN_CHA_SEED", threeMember.getFUserId());
                        assetCount = (AssetCount) result1.getData();
                        if (assetCount.getRemainder().compareTo(threeYunChaSeedMoney) >= 0) {
                            Result beanResult = this.assetCountService.saveRemainderAsset(threeMember.getFUserId(),"YUN_CHA_SEED","THREE_THAW_YUN_CHA_SEED", threeYunChaSeedMoney
                                    .negate(), order.getId(),"",new Date());
                            if (0 == beanResult.getCode()) {
                                this.assetCountService.saveRemainderAsset(threeMember.getFUserId(),"RMB","THREE_THAW_YUN_CHA_SEED", threeYunChaSeedMoney, order
                                        .getId(),"",new Date());
                            }
                        } else {
                            BigDecimal difference = twoYunChaSeedMoney.subtract(assetCount.getRemainder());
                            if (assetCount.getRemainder().compareTo(BigDecimal.ZERO) > 0) {
                                BigDecimal remainder = assetCount.getRemainder();
                                Result beanResult = this.assetCountService.saveRemainderAsset(threeMember.getFUserId(),"YUN_CHA_SEED","THREE_THAW_YUN_CHA_SEED", remainder
                                        .negate(), order.getId(),"",new Date());
                                if (0 == beanResult.getCode()) {
                                    this.assetCountService.saveRemainderAsset(threeMember.getFUserId(), "RMB","THREE_THAW_YUN_CHA_SEED", remainder, order
                                            .getId(),"",new Date());
                                }
                            }
                            Result result3 = this.assetCountService.findByTypeAndUserId("NEW_YUN_CHA_SEED", threeMember.getFUserId());
                            AssetCount assetCount3 = (AssetCount)result3.getData();
                            if (null != assetCount3 &&
                                    assetCount3.getRemainder().compareTo(BigDecimal.ZERO) > 0) {
                                if (assetCount3.getRemainder().compareTo(difference) > 0) {
                                    Result beanResult2 = this.assetCountService.saveRemainderAsset(threeMember.getFUserId(),"NEW_YUN_CHA_SEED", "THREE_THAW_YUN_CHA_SEED", difference
                                            .negate(), order.getId(),"",new Date());
                                    if (0 == beanResult2.getCode()) {
                                        this.assetCountService.saveRemainderAsset(threeMember.getFUserId(),"RMB","THREE_THAW_YUN_CHA_SEED", difference, order
                                                .getId(),"",new Date());
                                    }
                                } else {
                                    BigDecimal remainder = assetCount3.getRemainder();
                                    Result beanResult2 = this.assetCountService.saveRemainderAsset(threeMember.getFUserId(),"NEW_YUN_CHA_SEED", "THREE_THAW_YUN_CHA_SEED", remainder
                                            .negate(), order.getId(),"",new Date());
                                    if (0 == beanResult2.getCode()) {
                                        this.assetCountService.saveRemainderAsset(threeMember.getFUserId(),"RMB","THREE_THAW_YUN_CHA_SEED", remainder, order
                                                .getId(),"",new Date());
                                    }
                                }
                            }
                        }
                        //配置的间推奖励余额,105
                        Optional<ValueConfig> optiona4 = valueConfigRepository.findById("three_thaw_reward");
                        BigDecimal threeFee = new BigDecimal(optiona4.get().getValue());
                        BigDecimal threeFeeMoney = threeFee.multiply(new BigDecimal(order.getAmount().intValue()));
                        this.assetCountService.saveRemainderAsset(threeMember.getFUserId(),"RMB","THREE_THAW_REWARD", threeFeeMoney, order
                                .getId(), String.format("间推%s%s认养%s棵获得奖励", new Object[] { member.getName(), member.getMobile().replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"), order.getAmount() }),new Date());
                    }
                }
                if (null != parent.getFServiceId()) {
                    member.setFServiceId(parent.getFServiceId());
                }
            }
        }
    }


    public QueryResults<AdoptedTreeOrderView> pageAdoptedTreeOrderByUser(Long userId,Long adoptedTreeId,String code,
                                                                        int pageNum, int pageSize) {
        return pageAdoptedTreeOrder(userId,adoptedTreeId,"",code,"",null,null,pageNum,pageSize);
    }

    //@ANoRepeatRequest
    @Transactional
    public Result updateOfflinePay(Long adoptedTreeOrderId) {
        AdoptedTreeOrder adoptedTreeOrder = this.adoptedTreeOrderRepository.findById(adoptedTreeOrderId).get();
        if (!adoptedTreeOrder.getStatus().equals("UN_PAY")) {
            return Result.failed(101,"订单已支付");
        }
        adoptedTreeOrder.setPayChannel("OFFLINE");
        adoptedTreeOrder.setPayTime(new Date());
        paySuccess(adoptedTreeOrder);
        return Result.ok();
    }

    @Transactional(rollbackFor = {Exception.class})
    public Result requestBalancePay(Long orderId) {
        AdoptedTreeOrder order = this.adoptedTreeOrderRepository.findById(orderId).get();
        Member member = this.memberRepository.findByUserId(order.getfUserId());
        if (order == null) {
            return Result.failed(101,"订单不存在");
        }
        if (!order.getStatus().equals("UN_PAY")) {
            return Result.failed(101,"订单已支付");
        }
        if ("FREEZE".equals(member.getMemberStatus())) {
            return Result.failed(101,"账户已被冻结无法使用余额");
        }
        AssetCount assetCount = this.assetCountService.findByTypeAndUserId(EAssetType.RMB.getName(), order.getfUserId()).getData();
        //认养树-运维管理费（订单总金额的%6）
        BigDecimal opexManagerFeeRate = new BigDecimal(6);
        BigDecimal opexManagerFee = order.getTreeFee().multiply(opexManagerFeeRate.multiply(new BigDecimal("0.01")));
        if (assetCount.getRemainder().compareTo(order.getTreeFee().add(opexManagerFee)) < 0) {
            return Result.failed(101,"您当前余额不足，请选择其他支付方式");
        }
        order.setOpexManagerFee(opexManagerFee);
        order.setOrderFee(order.getTreeFee().add(order.getOpexManagerFee()));
        order.setPayFee(order.getOrderFee());
        order.setPayTime(new Date());
        order.setPayChannel("BALANCE");
        Result<AssetDetail> beanResult = this.assetCountService.saveRemainderAsset(order.getfUserId(),"RMB","ADOPTING_OIL_TEA_TREES", order
                .getPayFee().negate(), order.getId(),"",new Date());
        if (0!=beanResult.getCode()) {
            return Result.failed(101,beanResult.getMessage());
        }
        paySuccess(order);
        return Result.ok();
    }
    @Autowired
    private UserSessionManager userSessionManager;
    public Result adoptedTreeCount() {
        Integer count = this.adoptedTreeOrderRepository.adoptedTreeCount(userSessionManager.getUserId());
        return Result.ok(count);
    }

    public static void main(String[] args) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date da = format.parse("2024-01-01");
            if (da.compareTo(new Date()) > 0) {
                System.out.println(111);
            } else {
                System.out.println(222);
            }

        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    public Result delete(Long adoptedTreeOrderId) {
        adoptedTreeOrderRepository.deleteById(adoptedTreeOrderId);
        return Result.ok();
    }

    public Result findById(Long adoptedTreeOrderId) {
        return Result.ok( adoptedTreeOrderRepository.findById(adoptedTreeOrderId).get());
    }
}
